#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Build-in / Std
from collections import Counter

'''
Created on 2016年8月29日

@author: Hawk
'''

from Model import *
import unittest
import os
import datetime

class ModelTestcase(unittest.TestCase):
    def category_setup(self):
        # add Category data
        self.categories = [
                      {'name': 'Recreational'},
                      {'name': 'Motorcycle'},
                      {'name': 'Golf'},
                      {'name': 'Watch'},
                      ]
        for c in self.categories:
            cat = Category()
            cat.name = c['name']
            cat.save()

    def project_setup(self):
        self.projects = [
                    {'name': 'oregon7xx', 'category': 1, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 'zumo660', 'category': 2, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 'fenix3', 'category': 4, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 'fenix3hr', 'category': 4, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 'gpsmap64s', 'category': 1, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 'gpsmap64sc', 'category': 1, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 'gpsmap62sc', 'category': 1, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 's2', 'category': 3, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 's4', 'category': 3, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 's6', 'category': 3, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    {'name': 's20', 'category': 3, 'owner': 'Best', 'ee_owner': 'Kevin'},
                    ]
        for p in self.projects:
            pro = Project()
            pro.name = p['name']
            pro.category = p['category']
            pro.owner = p['owner']
            pro.ee_owner = p['ee_owner']
            pro.save()

    def sku_setup(self):
        self.skus = [
                {'name': 'APAC'},
                {'name': 'CHN'},
                {'name': 'TWN'},
                {'name': 'JPN'},
                {'name': 'KOR'},
                {'name': 'SEA'},
                {'name': 'IND'},
                ]
        for s in self.skus:
            sk = Sku()
            sk.name = s['name']
            sk.save()

    def project_sku_setup(self):
        self.project_skus = [
                {'name': 'APAC', 'project': 1, 'sku': 1, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},

                {'name': 'CHN', 'project': 2, 'sku': 2, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},
                {'name': 'TWN', 'project': 2, 'sku': 3, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},
                {'name': 'JPN', 'project': 2, 'sku': 4, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},

                {'name': 'CHN', 'project': 3, 'sku': 2, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},
                {'name': 'TWN', 'project': 3, 'sku': 3, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},
                {'name': 'JPN', 'project': 3, 'sku': 4, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},

                {'name': 'APAC', 'project': 4, 'sku': 1, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},

                {'name': 'CHN', 'project': 5, 'sku': 2, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},
                {'name': 'TWN', 'project': 5, 'sku': 3, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},
                {'name': 'JPN', 'project': 5, 'sku': 4, 'owner': 'Best', 'frm107_date': datetime.date(2016, 06, 01), 'mp_date': datetime.date(2016, 07, 01), 'development_mm': 0, 'maintenance_mm': 0},
                ]
        for s in self.project_skus:
            sk = Product()
            sk.project = s['project']
            sk.sku = s['sku']
            sk.owner = s['owner']
            sk.frm107_date = s['frm107_date']
            sk.mp_date = s['mp_date']
            sk.development_mm = s['development_mm']
            sk.maintenance_mm = s['maintenance_mm']
            sk.save()

    def record_setup(self):
        self.records = [
                   {'date': datetime.date(2016, 01, 01), 'product': 1, 'sku': 1, 'version':'2.00', 'ww_version': '2.20', 'development_mm': 0.5, 'maintenance_mm': 3, 'is_sync_ww': 0},
                   {'date': datetime.date(2016, 02, 01), 'product': 2, 'sku': 2, 'version':'2.00', 'ww_version': '2.20', 'development_mm': 0.5, 'maintenance_mm': 3, 'is_sync_ww': 0},
                   {'date': datetime.date(2016, 03, 01), 'product': 3, 'sku': 3, 'version':'2.00', 'ww_version': '2.20', 'development_mm': 0.53, 'maintenance_mm': 3, 'is_sync_ww': 0},
                   {'date': datetime.date(2016, 04, 01), 'product': 3, 'sku': 4, 'version':'2.00', 'ww_version': '2.20', 'development_mm': 0.53, 'maintenance_mm': 3, 'is_sync_ww': 0},
                   {'date': datetime.date(2016, 05, 01), 'product': 2, 'sku': 1, 'version':'2.00', 'ww_version': '2.20', 'development_mm': 0.52, 'maintenance_mm': 3, 'is_sync_ww': 0},
                   {'date': datetime.date(2016, 06, 01), 'product': 2, 'sku': 2, 'version':'2.10', 'ww_version': '2.20', 'development_mm': 0.51, 'maintenance_mm': 3, 'is_sync_ww': 0},
                   ]
        for r in self.records:
            rec = Record()
            rec.date = r['date'];
            rec.product = r['product'];
            rec.version = r['version'];
            rec.ww_version = r['ww_version'];
            rec.development_mm = r['development_mm'];
            rec.maintenance_mm = r['maintenance_mm'];
            rec.is_sync_ww = r['is_sync_ww'];
            rec.save()

        # update records
        for r in self.records:
            sk = Product.select().where(Product.id == r['sku']).get()
            sk.development_mm += r['development_mm']
            sk.maintenance_mm += r['maintenance_mm']
            sk.save()

    def setUp(self):
        self.db_name = 'model_test.db'
        self.database = SqliteDatabaseWarpper(self.db_name)

        self.database.register(Category)
        self.database.register(Project)
        self.database.register(Sku)
        self.database.register(Record)
        self.database.register(Product)
        self.database.register(Operation)

        self.database.connect()
        self.database.create_tables([Category, Project, Sku, Record, Product, Operation], safe=True)

        self.category_setup()
        self.project_setup()
        self.sku_setup()
        self.project_sku_setup()
        self.record_setup()

    def tearDown(self):
        self.database.close()
        if os.path.exists(self.db_name):
            #os.remove(self.db_name)
            pass

    def model_name_id_test(self, cls, name, exp_id):
        obj = cls.select().where(cls.name == name).get()
        self.assertEqual(exp_id, obj.id)

    def model_fields_test(self, cls, exp_fields):
        self.assertTrue(Counter(exp_fields) == Counter(cls.get_fields()))

    def test_category_model(self):
        self.model_fields_test(Category, ['update_time', 'comment', 'create_time', 'id', 'name', 'deleted'])

    def test_category(self):
        self.assertEqual(len(self.categories), Category.select().count())
        self.model_name_id_test(Category, 'Recreational', 1)
        self.model_name_id_test(Category, 'Motorcycle', 2)
        self.model_name_id_test(Category, 'Golf', 3)
        self.model_name_id_test(Category, 'Watch', 4)

    def test_project_model(self):
        self.model_fields_test(Project, ['id', 'name', 'category', 'owner', 'ee_owner', 'comment', 'deleted'])

    def test_project(self):
        self.assertEqual(len(self.projects), Project.select().count())
        self.model_name_id_test(Project, 'oregon7xx', 1)
        self.model_name_id_test(Project, 'zumo660', 2)
        self.model_name_id_test(Project, 'fenix3hr', 4)
        self.model_name_id_test(Project, 'gpsmap62sc', 7)
        self.model_name_id_test(Project, 's20', 11)

    def test_sku_model(self):
        self.model_fields_test(Sku, ['id', 'name', 'create_time', 'update_time', 'comment', 'deleted'])

    def test_sku(self):
        self.assertEqual(len(self.skus), Sku.select().count())
        self.model_name_id_test(Sku, 'APAC', 1)
        self.model_name_id_test(Sku, 'CHN', 2)
        self.model_name_id_test(Sku, 'TWN', 3)
        self.model_name_id_test(Sku, 'JPN', 4)
        self.model_name_id_test(Sku, 'KOR', 5)
        self.model_name_id_test(Sku, 'SEA', 6)
        self.model_name_id_test(Sku, 'IND', 7)

    def test_projectsku_model(self):
        self.model_fields_test(Product, ['id', 'project', 'sku', 'owner', 'deleted', 'frm107_date', 'mp_date', 'development_mm', 'maintenance_mm', 'comment'])

    def test_projectsku_data(self, idx, project, sku):
        pjs = Product.select().where(Product.id == idx).get()
        self.assertEqual(pjs.project.id, project)
        self.assertEqual(pjs.sku.id, sku)

    def test_projectsku(self):
        self.assertEqual(len(self.project_skus), Product.select().count())
        self.test_projectsku_data(1, 1, 1)
        self.test_projectsku_data(2, 2, 2)
        self.test_projectsku_data(3, 2, 3)
        self.test_projectsku_data(4, 2, 4)
        self.test_projectsku_data(5, 3, 2)

    def test_record_model(self):
        self.model_fields_test(Record, ['id', 'date', 'project', 'sku', 'version', 'deleted', 'ww_version', 'development_mm', 'maintenance_mm', 'is_sync_ww', 'comment'])

    def test_record_data(self, project, sku, date, version):
        record = Record.select().where((Record.project == project) & (Record.sku == sku) & (Record.date == date)).get()
        self.assertEqual(record.version, version)

    def test_record(self):
        self.assertEqual(len(self.skus), Sku.select().count())
        self.test_record_data(1, 1, datetime.date(2016, 01, 01), '2.00')
        self.test_record_data(2, 2, datetime.date(2016, 06, 01), '2.10')

if __name__ == "__main__":
    suite = unittest.TestSuite()

    suite.addTest(ModelTestcase('test_category_model'))
    suite.addTest(ModelTestcase('test_category'))
    suite.addTest(ModelTestcase('test_project_model'))
    suite.addTest(ModelTestcase('test_project'))
    suite.addTest(ModelTestcase('test_sku_model'))
    suite.addTest(ModelTestcase('test_sku'))
    suite.addTest(ModelTestcase('test_projectsku_model'))
    suite.addTest(ModelTestcase('test_projectsku'))
    suite.addTest(ModelTestcase('test_record_model'))
    suite.addTest(ModelTestcase('test_record'))
    runner = unittest.TextTestRunner()
    runner.run(suite)
